home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / gfx / show / svoUtah22.lha / svoUtahRLE / source / URT / lib / rle_getrow.c < prev    next >
C/C++ Source or Header  |  1990-08-02  |  16KB  |  604 lines

  1. /*
  2.  * This software is copyrighted as noted below.  It may be freely copied,
  3.  * modified, and redistributed, provided that the copyright notice is 
  4.  * preserved on all copies.
  5.  * 
  6.  * There is no warranty or other guarantee of fitness for this software,
  7.  * it is provided solely "as is".  Bug reports or fixes may be sent
  8.  * to the author, who may or may not act on them as he desires.
  9.  *
  10.  * You may not include this software in a program or other software product
  11.  * without supplying the source, or without informing the end-user that the 
  12.  * source is available for no extra charge.
  13.  *
  14.  * If you modify this software, you should include a notice giving the
  15.  * name of the person performing the modification, the date of modification,
  16.  * and the reason for such modification.
  17.  *
  18.  *  Modified at BRL 16-May-88 by Mike Muuss to avoid Alliant STDC desire
  19.  *  to have all "void" functions so declared.
  20.  */
  21. /* 
  22.  * rle_getrow.c - Read an RLE file in.
  23.  * 
  24.  * Author:    Spencer W. Thomas
  25.  *         Computer Science Dept.
  26.  *         University of Utah
  27.  * Date:    Wed Apr 10 1985
  28.  * Copyright (c) 1985 Spencer W. Thomas
  29.  * 
  30.  * $Id: rle_getrow.c,v 3.0 90/08/03 15:20:45 spencer Exp $
  31.  */
  32. #ifndef lint
  33. static char rcs_ident[] = "$Id: rle_getrow.c,v 3.0 90/08/03 15:20:45 spencer Exp $";
  34. #endif
  35.  
  36. #include "stdio.h"
  37. #include "rle.h"
  38. #include "rle_code.h"
  39. #ifdef USE_STDLIB_H
  40. #include <stdlib.h>
  41. #else
  42.  
  43. #ifdef USE_STRING_H
  44. #include <string.h>
  45. #else
  46. #include <strings.h>
  47. #endif
  48.  
  49. #ifndef VOID_STAR
  50. extern char * malloc();
  51. #else
  52. extern void *malloc();
  53. #endif
  54. extern void free();
  55.  
  56. #endif /* USE_STDLIB_H */
  57.  
  58. /* Read a two-byte "short" that started in VAX (LITTLE_ENDIAN) order */
  59. #define VAXSHORT( var, fp )\
  60.     { var = fgetc(fp)&0xFF; var |= (fgetc(fp)) << 8; }
  61.   
  62. /* Instruction format -- first byte is opcode, second is datum. */
  63.  
  64. #define OPCODE(inst) (inst[0] & ~LONG)
  65. #define LONGP(inst) (inst[0] & LONG)
  66. #define DATUM(inst) (inst[1] & 0xff)    /* Make sure it's unsigned. */
  67.  
  68. static int       debug_f;        /* If non-zero, print debug info. */
  69. static void    bfill();
  70. extern int vax_gshort();
  71.  
  72. /*****************************************************************
  73.  * TAG( rle_get_setup )
  74.  * 
  75.  * Read the initialization information from an RLE file.
  76.  * Inputs:
  77.  *     the_hdr:    Contains pointer to the input file.
  78.  * Outputs:
  79.  *     the_hdr:    Initialized with information from the
  80.  *            input file.
  81.  *    Returns 0 on success, -1 if the file is not an RLE file,
  82.  *    -2 if malloc of the color map failed, -3 if an immediate EOF
  83.  *    is hit (empty input file), and -4 if an EOF is encountered reading
  84.  *    the setup information.
  85.  * Assumptions:
  86.  *     infile points to the "magic" number in an RLE file (usually
  87.  * byte 0 in the file).
  88.  * Algorithm:
  89.  *     Read in the setup info and fill in the_hdr.
  90.  */
  91. int
  92. rle_get_setup( the_hdr )
  93. rle_hdr * the_hdr;
  94. {
  95.     struct XtndRsetup setup;
  96.     short magic;
  97.     register FILE *infile = the_hdr->rle_file;
  98.     rle_pixel * bg_color;
  99.     register int i;
  100.     char * comment_buf;
  101.  
  102.     VAXSHORT( magic, infile );
  103.     if ( feof( infile ) )
  104.     return RLE_EMPTY;
  105.     if ( magic != RLE_MAGIC )
  106.     return RLE_NOT_RLE;
  107.     fread( &setup, 1, SETUPSIZE, infile );  /* assume VAX packing */
  108.     if ( feof( infile ) )
  109.     return RLE_EOF;
  110.  
  111.     /* Extract information from setup */
  112.     the_hdr->ncolors = setup.h_ncolors;
  113.     for ( i = 0; i < the_hdr->ncolors; i++ )
  114.     RLE_SET_BIT( *the_hdr, i );
  115.  
  116.     if ( !(setup.h_flags & H_NO_BACKGROUND) )
  117.     {
  118.     the_hdr->bg_color = (int *)malloc(
  119.         (unsigned)(sizeof(int) * setup.h_ncolors) );
  120.     bg_color = (rle_pixel *)malloc(
  121.         (unsigned)(1 + (setup.h_ncolors / 2) * 2) );
  122.     fread( (char *)bg_color, 1, 1 + (setup.h_ncolors / 2) * 2, infile );
  123.     for ( i = 0; i < setup.h_ncolors; i++ )
  124.         the_hdr->bg_color[i] = bg_color[i];
  125.     free( bg_color );
  126.     }
  127.     else
  128.     {
  129.     (void)getc( infile );    /* skip filler byte */
  130.     the_hdr->bg_color = NULL;
  131.     }
  132.  
  133.     if ( setup.h_flags & H_NO_BACKGROUND )
  134.     the_hdr->background = 0;
  135.     else if ( setup.h_flags & H_CLEARFIRST )
  136.     the_hdr->background = 2;
  137.     else
  138.     the_hdr->background = 1;
  139.     if ( setup.h_flags & H_ALPHA )
  140.     {
  141.     the_hdr->alpha = 1;
  142.     RLE_SET_BIT( *the_hdr, RLE_ALPHA );
  143.     }
  144.     else
  145.     the_hdr->alpha = 0;
  146.  
  147.     the_hdr->xmin = vax_gshort( setup.hc_xpos );
  148.     the_hdr->ymin = vax_gshort( setup.hc_ypos );
  149.     the_hdr->xmax = the_hdr->xmin + vax_gshort( setup.hc_xlen ) - 1;
  150.     the_hdr->ymax = the_hdr->ymin + vax_gshort( setup.hc_ylen ) - 1;
  151.  
  152.     the_hdr->ncmap = setup.h_ncmap;
  153.     the_hdr->cmaplen = setup.h_cmaplen;
  154.     if ( the_hdr->ncmap > 0 )
  155.     {
  156.     register int maplen =
  157.              the_hdr->ncmap * (1 << the_hdr->cmaplen);
  158.     register int i;
  159.     register char *maptemp;
  160.  
  161.     the_hdr->cmap = (rle_map *)malloc(
  162.         (unsigned)(sizeof(rle_map) * maplen) );
  163.     maptemp = (char *)malloc( 2 * maplen );
  164.     if ( the_hdr->cmap == NULL || maptemp == NULL )
  165.     {
  166.         fprintf( stderr,
  167.         "Malloc failed for color map of size %d*%d in rle_get_setup\n",
  168.         the_hdr->ncmap, (1 << the_hdr->cmaplen) );
  169.         return RLE_NO_SPACE;
  170.     }
  171.     fread( maptemp, sizeof(short), maplen, infile );
  172.     for ( i = 0; i < maplen; i++ )
  173.         the_hdr->cmap[i] = vax_gshort( &maptemp[i * 2] );
  174.     free( maptemp );
  175.     }
  176.  
  177.     /* Check for comments */
  178.     if ( setup.h_flags & H_COMMENT )
  179.     {
  180.     short comlen, evenlen;
  181.     register char * cp;
  182.  
  183.     VAXSHORT( comlen, infile );    /* get comment length */
  184.     evenlen = (comlen + 1) & ~1;    /* make it even */
  185.     if ( evenlen )
  186.     {
  187.         comment_buf = (char *)malloc( (unsigned) evenlen );
  188.     
  189.         if ( comment_buf == NULL )
  190.         {
  191.         fprintf( stderr,
  192.      "Malloc failed for comment buffer of size %d in rle_get_setup\n",
  193.              comlen );
  194.         return RLE_NO_SPACE;
  195.         }
  196.         fread( comment_buf, 1, evenlen, infile );
  197.         /* Count the comments */
  198.         for ( i = 0, cp = comment_buf; cp < comment_buf + comlen; cp++ )
  199.         if ( *cp == 0 )
  200.             i++;
  201.         i++;            /* extra for NULL pointer at end */
  202.         /* Get space to put pointers to comments */
  203.         the_hdr->comments =
  204.         (CONST_DECL char **)malloc( (unsigned)(i * sizeof(char *)) );
  205.         if ( the_hdr->comments == NULL )
  206.         {
  207.         fprintf( stderr,
  208.         "Malloc failed for %d comment pointers in rle_get_setup\n",
  209.              i );
  210.         return RLE_NO_SPACE;
  211.         }
  212.         /* Get pointers to the comments */
  213.         *the_hdr->comments = comment_buf;
  214.         for ( i = 1, cp = comment_buf + 1;
  215.           cp < comment_buf + comlen;
  216.           cp++ )
  217.         if ( *(cp - 1) == 0 )
  218.             the_hdr->comments[i++] = cp;
  219.         the_hdr->comments[i] = NULL;
  220.     }
  221.     else
  222.         the_hdr->comments = NULL;
  223.     }
  224.     else
  225.     the_hdr->comments = NULL;
  226.  
  227.     /* Initialize state for rle_getrow */
  228.     the_hdr->priv.get.scan_y = the_hdr->ymin;
  229.     the_hdr->priv.get.vert_skip = 0;
  230.     the_hdr->priv.get.is_eof = 0;
  231.     the_hdr->priv.get.is_seek = ftell( infile ) > 0;
  232.     debug_f = 0;
  233.  
  234.     if ( !feof( infile ) )
  235.     return RLE_SUCCESS;    /* success! */
  236.     else
  237.     {
  238.     the_hdr->priv.get.is_eof = 1;
  239.     return RLE_EOF;
  240.     }
  241. }
  242.  
  243.  
  244. /*****************************************************************
  245.  * TAG( rle_get_error )
  246.  * 
  247.  * Print an error message for the return code from rle_get_setup
  248.  * Inputs:
  249.  *     code:        The return code from rle_get_setup.
  250.  *    pgmname:    Name of this program (argv[0]).
  251.  *    fname:        Name of the input file.
  252.  * Outputs:
  253.  *     Prints an error message on standard output.
  254.  *    Returns code.
  255.  */
  256. int
  257. rle_get_error( code, pgmname, fname )
  258. int code;
  259. CONST_DECL char *pgmname;
  260. CONST_DECL char *fname;
  261. {
  262.     if (! fname)
  263.     fname = "Standard Input";
  264.     if ( strcmp( fname, "-" ) == 0 )
  265.     fname = "Standard Input";
  266.  
  267.     switch( code )
  268.     {
  269.     case RLE_SUCCESS:        /* success */
  270.     break;
  271.  
  272.     case RLE_NOT_RLE:        /* Not an RLE file */
  273.     fprintf( stderr, "%s: %s is not an RLE file\n",
  274.          pgmname, fname );
  275.     break;
  276.  
  277.     case RLE_NO_SPACE:            /* malloc failed */
  278.     fprintf( stderr,
  279.          "%s: Malloc failed reading header of file %s\n",
  280.          pgmname, fname );
  281.     break;
  282.  
  283.     case RLE_EMPTY:
  284.     fprintf( stderr, "%s: %s is an empty file\n", pgmname, fname );
  285.     break;
  286.  
  287.     case RLE_EOF:
  288.     fprintf( stderr,
  289.          "%s: RLE header of %s is incomplete (premature EOF)\n",
  290.          pgmname, fname );
  291.     break;
  292.  
  293.     default:
  294.     fprintf( stderr, "%s: Error encountered reading header of %s\n",
  295.          pgmname, fname );
  296.     break;
  297.     }
  298.     return code;
  299. }
  300.  
  301.  
  302. /*****************************************************************
  303.  * TAG( rle_get_setup_ok )
  304.  * 
  305.  * Read the initialization information from an RLE file.
  306.  * Inputs:
  307.  *     the_hdr:    Contains pointer to the input file.
  308.  *    prog_name:  Program name to be printed in the error message.
  309.  *      file_name:  File name to be printed in the error message.
  310.  *                  If NULL, the string "stdin" is generated.
  311.  * Outputs:
  312.  *     the_hdr:    Initialized with information from the
  313.  *            input file.
  314.  *      If reading the header fails, it prints an error message
  315.  *    and exits with the appropriate status code.
  316.  * Algorithm:
  317.  *     rle_get_setup does all the work.
  318.  */
  319. void
  320. rle_get_setup_ok( the_hdr, prog_name, file_name )
  321. rle_hdr * the_hdr;
  322. CONST_DECL char *prog_name;
  323. CONST_DECL char *file_name;
  324. {
  325.     int code;
  326.  
  327.     code = rle_get_error( rle_get_setup( the_hdr ), prog_name, file_name );
  328.     if (code)
  329.     exit( code );
  330. }
  331.  
  332.  
  333. /*****************************************************************
  334.  * TAG( rle_debug )
  335.  * 
  336.  * Turn RLE debugging on or off.
  337.  * Inputs:
  338.  *     on_off:        if 0, stop debugging, else start.
  339.  * Outputs:
  340.  *     Sets internal debug flag.
  341.  * Assumptions:
  342.  *    [None]
  343.  * Algorithm:
  344.  *    [None]
  345.  */
  346. void
  347. rle_debug( on_off )
  348. int on_off;
  349. {
  350.     debug_f = on_off;
  351.  
  352.     /* Set line buffering on stderr.  Character buffering is the default, and
  353.      * it is SLOOWWW for large amounts of output.
  354.      */
  355.     setlinebuf( stderr );
  356. }
  357.  
  358.  
  359. /*****************************************************************
  360.  * TAG( rle_getrow )
  361.  * 
  362.  * Get a scanline from the input file.
  363.  * Inputs:
  364.  *    the_hdr:    Header structure containing information about 
  365.  *            the input file.
  366.  * Outputs:
  367.  *     scanline:   an array of pointers to the individual color
  368.  *            scanlines.  Scanline is assumed to have
  369.  *            the_hdr->ncolors pointers to arrays of rle_pixel,
  370.  *            each of which is at least the_hdr->xmax+1 long.
  371.  *    Returns the current scanline number.
  372.  * Assumptions:
  373.  *     rle_get_setup has already been called.
  374.  * Algorithm:
  375.  *     If a vertical skip is being executed, and clear-to-background is
  376.  *    specified (the_hdr->background is true), just set the
  377.  *    scanlines to the background color.  If clear-to-background is
  378.  *    not set, just increment the scanline number and return.
  379.  * 
  380.  *    Otherwise, read input until a vertical skip is encountered,
  381.  *    decoding the instructions into scanline data.
  382.  *
  383.  *    If ymax is reached (or, somehow, passed), continue reading and
  384.  *    discarding input until end of image.
  385.  */
  386. int
  387. rle_getrow( the_hdr, scanline )
  388. rle_hdr * the_hdr;
  389. rle_pixel *scanline[];
  390. {
  391.     register rle_pixel * scanc;
  392.     register int nc;
  393.     register FILE *infile = the_hdr->rle_file;
  394.     int scan_x = the_hdr->xmin,    /* current X position */
  395.        channel = 0;            /* current color channel */
  396.     short word, long_data;
  397.     char inst[2];
  398.  
  399.     /* Clear to background if specified */
  400.     if ( the_hdr->background == 2 )
  401.     {
  402.     if ( the_hdr->alpha && RLE_BIT( *the_hdr, -1 ) )
  403.         bfill( (char *)scanline[-1], the_hdr->xmax + 1, 0 );
  404.     for ( nc = 0; nc < the_hdr->ncolors; nc++ )
  405.         if ( RLE_BIT( *the_hdr, nc ) )
  406.         bfill( (char *)scanline[nc], the_hdr->xmax+1,
  407.             the_hdr->bg_color[nc] );
  408.     }
  409.  
  410.     /* If skipping, then just return */
  411.     if ( the_hdr->priv.get.vert_skip > 0 )
  412.     {
  413.     the_hdr->priv.get.vert_skip--;
  414.     the_hdr->priv.get.scan_y++;
  415.     if ( the_hdr->priv.get.vert_skip > 0 )
  416.         if ( the_hdr->priv.get.scan_y >= the_hdr->ymax )
  417.         {
  418.         int y = the_hdr->priv.get.scan_y;
  419.         while ( rle_getskip( the_hdr ) != 32768 )
  420.             ;
  421.         return y;
  422.         }
  423.         else
  424.         return the_hdr->priv.get.scan_y;
  425.     }
  426.  
  427.     /* If EOF has been encountered, return also */
  428.     if ( the_hdr->priv.get.is_eof )
  429.     return ++the_hdr->priv.get.scan_y;
  430.  
  431.     /* Otherwise, read and interpret instructions until a skipLines
  432.      * instruction is encountered.
  433.      */
  434.     if ( RLE_BIT( *the_hdr, channel ) )
  435.     scanc = scanline[channel] + scan_x;
  436.     else
  437.     scanc = NULL;
  438.     for (;;)
  439.     {
  440.     inst[0] = getc( infile );
  441.     inst[1] = getc( infile );
  442.     if ( feof(infile) )
  443.     {
  444.         the_hdr->priv.get.is_eof = 1;
  445.         break;        /* <--- one of the exits */
  446.     }
  447.  
  448.     switch( OPCODE(inst) )
  449.     {
  450.     case RSkipLinesOp:
  451.         if ( LONGP(inst) )
  452.         {
  453.         VAXSHORT( the_hdr->priv.get.vert_skip, infile );
  454.         }
  455.         else
  456.         the_hdr->priv.get.vert_skip = DATUM(inst);
  457.         if (debug_f)
  458.         fprintf(stderr, "Skip %d Lines (to %d)\n",
  459.             the_hdr->priv.get.vert_skip,
  460.             the_hdr->priv.get.scan_y +
  461.                 the_hdr->priv.get.vert_skip );
  462.  
  463.         break;            /* need to break for() here, too */
  464.  
  465.     case RSetColorOp:
  466.         channel = DATUM(inst);    /* select color channel */
  467.         if ( channel == 255 )
  468.         channel = -1;
  469.         scan_x = the_hdr->xmin;
  470.         if ( RLE_BIT( *the_hdr, channel ) )
  471.         scanc = scanline[channel]+scan_x;
  472.         if ( debug_f )
  473.         fprintf( stderr, "Set color to %d (reset x to %d)\n",
  474.              channel, scan_x );
  475.         break;
  476.  
  477.     case RSkipPixelsOp:
  478.         if ( LONGP(inst) )
  479.         {
  480.         VAXSHORT( long_data, infile );
  481.         scan_x += long_data;
  482.         scanc += long_data;
  483.         if ( debug_f )
  484.             fprintf( stderr, "Skip %d pixels (to %d)\n",
  485.                 long_data, scan_x );
  486.              
  487.         }
  488.         else
  489.         {
  490.         scan_x += DATUM(inst);
  491.         scanc += DATUM(inst);
  492.         if ( debug_f )
  493.             fprintf( stderr, "Skip %d pixels (to %d)\n",
  494.                 DATUM(inst), scan_x );
  495.         }
  496.         break;
  497.  
  498.     case RByteDataOp:
  499.         if ( LONGP(inst) )
  500.         {
  501.         VAXSHORT( nc, infile );
  502.         }
  503.         else
  504.         nc = DATUM(inst);
  505.         nc++;
  506.         if ( RLE_BIT( *the_hdr, channel ) )
  507.         {
  508.         fread( (char *)scanc, 1, nc, infile );
  509.         if ( nc & 1 )
  510.             (void)getc( infile );    /* throw away odd byte */
  511.         }
  512.         else
  513.         if ( the_hdr->priv.get.is_seek )
  514.             fseek( infile, ((nc + 1) / 2) * 2, 1 );
  515.         else
  516.         {
  517.             register int ii;
  518.             for ( ii = ((nc + 1) / 2) * 2; ii > 0; ii-- )
  519.             (void) getc( infile );    /* discard it */
  520.         }
  521.  
  522.         scanc += nc;
  523.         scan_x += nc;
  524.         if ( debug_f )
  525.         if ( RLE_BIT( *the_hdr, channel ) )
  526.         {
  527.             rle_pixel * cp = scanc - nc;
  528.             fprintf( stderr, "Pixel data %d (to %d):", nc, scan_x );
  529.             for ( ; nc > 0; nc-- )
  530.             fprintf( stderr, "%02x", *cp++ );
  531.             putc( '\n', stderr );
  532.         }
  533.         else
  534.         fprintf( stderr, "Pixel data %d (to %d)\n", nc, scan_x );
  535.         break;
  536.  
  537.     case RRunDataOp:
  538.         if ( LONGP(inst) )
  539.         {
  540.         VAXSHORT( nc, infile );
  541.         }
  542.         else
  543.         nc = DATUM(inst);
  544.         scan_x += nc + 1;
  545.  
  546.         VAXSHORT( word, infile );
  547.         if ( debug_f )
  548.         fprintf( stderr, "Run length %d (to %d), data %02x\n",
  549.                 nc + 1, scan_x, word );
  550.         if ( RLE_BIT( *the_hdr, channel ) )
  551.         {
  552.         if ( nc >= 10 )        /* break point for 785, anyway */
  553.         {
  554.             bfill( (char *)scanc, nc + 1, word );
  555.             scanc += nc + 1;
  556.         }
  557.         else
  558.             for ( ; nc >= 0; nc--, scanc++ )
  559.             *scanc = word;
  560.         }
  561.         break;
  562.  
  563.     case REOFOp:
  564.         the_hdr->priv.get.is_eof = 1;
  565.         if ( debug_f )
  566.         fprintf( stderr, "End of Image\n" );
  567.         break;
  568.  
  569.     default:
  570.         fprintf( stderr,
  571.              "rle_getrow: Unrecognized opcode: %d\n", inst[0] );
  572.         exit(1);
  573.     }
  574.     if ( OPCODE(inst) == RSkipLinesOp || OPCODE(inst) == REOFOp )
  575.         break;            /* <--- the other loop exit */
  576.     }
  577.  
  578.     /* If at end, skip the rest of a malformed image. */
  579.     if ( the_hdr->priv.get.scan_y >= the_hdr->ymax )
  580.     {
  581.     int y = the_hdr->priv.get.scan_y;
  582.     while ( rle_getskip( the_hdr ) != 32768 )
  583.         ;
  584.     return y;
  585.     }
  586.  
  587.     return the_hdr->priv.get.scan_y;
  588. }
  589.  
  590.  
  591. /* Fill buffer at s with n copies of character c.  N must be <= 65535*/
  592. /* ARGSUSED */
  593. static void bfill( s, n, c )
  594. register char *s;
  595. register int n, c;
  596. {
  597. #ifdef vax
  598.     asm("   movc5   $0,*4(ap),12(ap),8(ap),*4(ap)");
  599. #else
  600.     while ( n-- > 0 )
  601.     *s++ = c;
  602. #endif
  603. }
  604.